package com.lihaozhe.config;

import com.lihaozhe.handler.DefaultAccessDeniedHandler;
import com.lihaozhe.handler.LoginAuthenticationFailureHandler;
import com.lihaozhe.handler.LoginAuthenticationSuccessHandler;
import com.lihaozhe.service.UserService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;

import javax.sql.DataSource;

/**
 * @author 李昊哲
 * @version 1.0
 * 2021/12/10 下午1:38
 */
@RequiredArgsConstructor
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled=true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    private final LoginAuthenticationSuccessHandler loginAuthenticationSuccessHandler;
    private final LoginAuthenticationFailureHandler loginAuthenticationFailureHandler;
    private final DefaultAccessDeniedHandler defaultAccessDeniedHandler;
    private final PersistentTokenRepository persistentTokenRepository;
    private final UserService userService;

    @Override
    public void configure(WebSecurity web) throws Exception {
        String[] permitPaths = {
                "/css/**",
                "/assets/**",
                "/swagger-ui.html",
                "/swagger-resources/**",
                "/webjars/**",
                "/*/api-docs",
                "/druid/**"
        };
        //解决静态资源被拦截的问题
        web.ignoring().antMatchers(permitPaths);
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .formLogin()
                .loginPage("/toLoginPage")// 用户未登录时，访问任何资源都转跳到该路径，即登录页面
                .loginProcessingUrl("/login")// 登录表单form中action的地址，也就是处理认证请求的路径
                .usernameParameter("account")// 登录表单form中用户名输入框input的name名，不修改的话默认是 account
                .passwordParameter("authString")// form中密码输入框input的name名，不修改的话默认是 authString
                .defaultSuccessUrl("/toIndexPage")// 登录认证成功后默认转跳的路径
                .successForwardUrl("/toSuccessPage")// 登录成功后跳转页面 必须是post请求
                .failureForwardUrl("/toFaieldPage")// 登录失败后跳转页面 必须是post请求
                // .successHandler(loginAuthenticationSuccessHandler)// 登录成功后访问默认请求后端处理器
                // .failureHandler(loginAuthenticationFailureHandler)// 登录失败后访问默认请求后端处理器
                .and()
                .authorizeRequests()
                .antMatchers("/toLoginPage").permitAll()// 不需要通过登录验证就可以被访问的资源路径
                // .antMatchers("/admin/**").hasAnyAuthority("ROLE_admin", "ROLE_lhz")  //前面是资源的访问路径、后面是资源的名称或者叫资源ID
                // .antMatchers("/admin/**").access("hasAnyAuthority('ROLE_admin','ROLE_lhz')")  //前面是资源的访问路径、后面是资源的名称或者叫资源ID
                // .antMatchers("/admin/**").hasAnyRole("admin", "user") // 前面是资源的访问路径、后面是角色的名称或者叫角色ID 自动加ROLE_前缀
                // .antMatchers("/admin/**").access("hasAnyRole('admin','user')") // 前面是资源的访问路径、后面是角色的名称或者叫角色ID 自动加ROLE_前缀
                // .antMatchers("/admin/**").access("hasIpAddress('192.168.1.104')")// 前面是资源的访问路径、后面是IP
                .anyRequest().authenticated()
                .and()
                .exceptionHandling().accessDeniedHandler(defaultAccessDeniedHandler)  // 异常处理
                .and()
                .logout().logoutUrl("/toLogout").logoutSuccessUrl("/toLoginPage").invalidateHttpSession(true).clearAuthentication(true)
                .and()
                .rememberMe().tokenRepository(persistentTokenRepository)
                .tokenValiditySeconds(60).userDetailsService(userService); // 退出登录
        // http.csrf().disable(); //禁用跨站csrf攻击防御，后面的章节会专门讲解
        // 第一部分是formLogin配置段，用于配置登录验证逻辑相关的信息。如：登录页面、登录成功页面、登录请求处理路径等。
        // 第二部分是authorizeRequests配置端，用于配置资源的访问权限。如：开发登录页面的permitAll开放访问，
    }
}